home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / vm / sun3.md / vmSunAsm.s < prev    next >
Encoding:
Text File  |  1992-12-19  |  23.5 KB  |  873 lines

  1.  
  2. |* vmSun.s -
  3. |*
  4. |*    Subroutines to access Sun virtual memory mapping hardware.
  5. |*    All of the routines in here assume that source and destination
  6. |*    function codes are set to MMU space.
  7. |*
  8. |* Copyright (C) 1985 Regents of the University of California
  9. |* All rights reserved.
  10. |*
  11.  
  12. #include "vmSunConst.h"
  13. #include "machAsmDefs.h"
  14.  
  15.     .data
  16.     .asciz "$Header: /cdrom/src/kernel/Cvsroot/kernel/vm/sun3.md/vmSunAsm.s,v 1.5 91/09/10 18:30:20 rab Exp $ SPRITE (Berkeley)"
  17.     .even
  18.     .text
  19.  
  20.  
  21. |*
  22. |* ----------------------------------------------------------------------------
  23. |*
  24. |* VmMachReadPTE --
  25. |*
  26. |*         Map the given hardware pmeg into the kernel's address space and 
  27. |*    return the pte at the corresponding address.  There is a reserved
  28. |*    address in the kernel that is used to map this hardware pmeg.
  29. |*
  30. |*    VmMachPTE VmMachReadPTE(pmegNum, addr)
  31. |*        int        pmegNum;/* The pmeg to read the PTE for. */
  32. |*        Address    addr;    /* The virtual address to read the PTE for. */
  33. |*
  34. |* Results:
  35. |*     The value of the PTE.
  36. |*
  37. |* Side effects:
  38. |*     None.
  39. |*
  40. |* ----------------------------------------------------------------------------
  41. |*
  42.     .globl    _VmMachReadPTE
  43. _VmMachReadPTE:
  44. |* 
  45. |* Set the segment map entry.
  46. |*
  47.     movl    _vmMachPTESegAddr,a0    | Get access address
  48.     addl    #VMMACH_SEG_MAP_OFF,a0    | Bump to segment map offset
  49.     movl    sp@(4),d0        | Get segment map entry to write.
  50.     movsb    d0,a0@            | Write segment map entry
  51.  
  52. |*
  53. |* Get the page map entry.
  54. |*
  55.     movl    sp@(8),d0        | Get virtual address
  56.     andw    #VMMACH_PAGE_MAP_MASK,d0| Mask out low bits
  57.     addl    #VMMACH_PAGE_MAP_OFF,d0    | Add in page map offset.
  58.     movl    d0, a0
  59.     movsl    a0@,d0            | d0 <= page map entry
  60.  
  61.     rts                    | Return
  62.  
  63.  
  64. |*
  65. |* ----------------------------------------------------------------------------
  66. |*
  67. |* VmMachWritePTE --
  68. |*
  69. |*         Map the given hardware pmeg into the kernel's address space and 
  70. |*    write the pte at the corresponding address.  There is a reserved
  71. |*    address in the kernel that is used to map this hardware pmeg.
  72. |*
  73. |*    void VmMachWritePTE(pmegNum, addr, pte)
  74. |*        int           pmegNum;    /* The pmeg to write the PTE for. */
  75. |*        Address    addr;        /* The address to write the PTE for. */
  76. |*        VmMachPTE    pte;        /* The page table entry to write. */
  77. |*
  78. |* Results:
  79. |*     None.
  80. |*
  81. |* Side effects:
  82. |*     The hardware page table entry is set.
  83. |*
  84. |* ----------------------------------------------------------------------------
  85. |*
  86.     .globl    _VmMachWritePTE
  87. _VmMachWritePTE:
  88. |* 
  89. |* Set the segment map entry.
  90. |*
  91.     movl    _vmMachPTESegAddr,a0    | Get access address
  92.     addl    #VMMACH_SEG_MAP_OFF,a0    | Bump to segment map offset
  93.     movl    sp@(4),d0        | Get segment map entry to write.
  94.     movsb    d0,a0@            | Write segment map entry
  95.  
  96. |*
  97. |* Set the page map entry.
  98. |*
  99.     movl    sp@(8),d0        | Get virtual address into a register
  100.     andw    #VMMACH_PAGE_MAP_MASK,d0    | Mask out low bits
  101.     addl    #VMMACH_PAGE_MAP_OFF,d0    | Add in page map offset.
  102.     movl    d0, a0
  103.     movl    sp@(12),d0        | Get page map entry into a register
  104.     movsl    d0,a0@            | Write page map entry
  105.  
  106.     rts                    | Return
  107.  
  108. |*
  109. |* ----------------------------------------------------------------------------
  110. |*
  111. |* VmMachGetPageMap --
  112. |*
  113. |*         Return the page map entry for the given virtual address.
  114. |*    It is assumed that the user context register is set to the context
  115. |*    for which the page map entry is to retrieved.
  116. |*
  117. |*    int Vm_GetPageMap(virtualAddress)
  118. |*        Address virtualAddress;
  119. |*
  120. |* Results:
  121. |*     The contents of the hardware page map entry.
  122. |*
  123. |* Side effects:
  124. |*     None.
  125. |*
  126. |* ----------------------------------------------------------------------------
  127. |*
  128.     .globl    _VmMachGetPageMap
  129. _VmMachGetPageMap:
  130.     movl    sp@(4),d0        | Get virtual address into a register
  131.     andw    #VMMACH_PAGE_MAP_MASK,d0| Get relevant bits from address.
  132.     addl    #VMMACH_PAGE_MAP_OFF,d0    | Add in page map offset.
  133.     movl    d0, a0
  134.     movsl    a0@,d0            | Read page map entry
  135.  
  136.     rts                    | Return
  137.  
  138. |*
  139. |* ----------------------------------------------------------------------------
  140. |*
  141. |* VmMachGetSegMap --
  142. |*
  143. |*         Return the segment map entry for the given virtual address.
  144. |*    It is assumed that the user context register is set to the context
  145. |*    for which the segment map entry is to retrieved.
  146. |*
  147. |*    int VmMachGetSegMap(virtualAddress)
  148. |*        Address virtualAddress;
  149. |*
  150. |* Results:
  151. |*     The contents of the segment map entry.
  152. |*
  153. |* Side effects:
  154. |*     None.
  155. |*
  156. |* ----------------------------------------------------------------------------
  157. |*
  158.     .globl    _VmMachGetSegMap
  159. _VmMachGetSegMap:
  160.     movl    sp@(4),d0        | Get virtual address in a register.
  161.     andw    #VMMACH_SEG_MAP_MASK,d0    | Get relevant bits.
  162.     addl    #VMMACH_SEG_MAP_OFF,d0    | Add in segment map offset
  163.     movl    d0, a0
  164.     clrl    d0            | Clear the return register.
  165.     movsb    a0@,d0            | Read segment map entry into return
  166.                     | register.
  167.  
  168.     rts                    | Return
  169.  
  170. |*
  171. |* ----------------------------------------------------------------------------
  172. |*
  173. |* VmMachSetPageMap --
  174. |*
  175. |*         Set the page map entry for the given virtual address to the pte valud 
  176. |*      given in pte.  It is assumed that the user context register is 
  177. |*    set to the context for which the page map entry is to be set.
  178. |*
  179. |*    void VmMachSetPageMap(virtualAddress, pte)
  180. |*        Address     virtualAddress;
  181. |*        VmMachPTE    pte;
  182. |*
  183. |* Results:
  184. |*     None.
  185. |*
  186. |* Side effects:
  187. |*     The hardware page map entry is set.
  188. |*
  189. |* ----------------------------------------------------------------------------
  190. |*
  191.     .globl    _VmMachSetPageMap
  192. _VmMachSetPageMap:
  193.     movl    sp@(4),d0        | Get virtual address into a register
  194.     andw    #VMMACH_PAGE_MAP_MASK,d0| Mask out low bits
  195.     addl    #VMMACH_PAGE_MAP_OFF,d0    | Add in page map offset.
  196.     movl    d0, a0
  197.     movl    sp@(8),d0        | Get page map entry into a register
  198.     movsl    d0,a0@            | Write page map entry
  199.  
  200.     rts                    | Return
  201.  
  202. |*
  203. |* ----------------------------------------------------------------------------
  204. |*
  205. |* VmMachPMEGZero --
  206. |*
  207. |*         Set all of the page table entries in the pmeg to 0.  There is a special
  208. |*    address in the kernel's address space (vmMachPTESegAddr) that is used to
  209. |*    map the pmeg in so that it can be zeroed.
  210. |*
  211. |*    void VmMachPMEGZero(pmeg)
  212. |*        int pmeg;
  213. |*
  214. |* Results:
  215. |*     None.
  216. |*
  217. |* Side effects:
  218. |*     The given pmeg is zeroed.
  219. |*
  220. |* ----------------------------------------------------------------------------
  221. |*
  222.  
  223.     .globl    _VmMachPMEGZero
  224. _VmMachPMEGZero:
  225. | Write segment map entry
  226.     movl    _vmMachPMEGSegAddr, d1    
  227.     movl    d1, a0            
  228.     addl    #VMMACH_SEG_MAP_OFF, a0    | a0 <= Segment map address    
  229.     movl    sp@(4),d0        | d0 <= PMEG num
  230.     movsb    d0,a0@            | Write PMEG num to segment map
  231.  
  232. | Now zero out all page table entries.
  233.  
  234.     movl    d1, a0            | a0 <= Starting address
  235.     addl    #VMMACH_PAGE_MAP_OFF, a0
  236.                     | d1 <= Ending address
  237.     addl    #(VMMACH_SEG_SIZE + VMMACH_PAGE_MAP_OFF), d1    
  238.     clrl    d0            | Clear out d0.
  239. 1:
  240.     movsl    d0,a0@            | Write page map entry
  241.     addl    #VMMACH_PAGE_SIZE_INT, a0 | Go to next address.
  242.     cmpl    a0, d1            | See if have initialized all 
  243.     bgt        1b            |     ptes.
  244.  
  245.     rts                    | Return
  246.  
  247. |*
  248. |* ----------------------------------------------------------------------------
  249. |*
  250. |* VmMachReadAndZeroPMEG --
  251. |*
  252. |*    Read out all page table entries in the given pmeg and then set each to
  253. |*    zero. There is a special address in the kernel's address space 
  254. |*    (vmMachPTESegAddr) that is used to access the PMEG.
  255. |*
  256. |*    void VmMachPMEGZero(pmeg, pteArray)
  257. |*        int     pmeg;
  258. |*        VmMachPTE    pteArray[VMMACH_NUM_PAGES_PER_SEG];
  259. |*
  260. |* Results:
  261. |*      None.
  262. |*
  263. |* Side effects:
  264. |*     The given pmeg is zeroed and *pteArray is filled in with the contents
  265. |*    of the PMEG before it is zeroed.
  266. |*
  267. |* ----------------------------------------------------------------------------
  268. |*
  269.  
  270.     .globl    _VmMachReadAndZeroPMEG
  271. _VmMachReadAndZeroPMEG:
  272.     movl    _vmMachPMEGSegAddr, a0
  273.     addl    #VMMACH_SEG_MAP_OFF, a0        | a0 <= Segment map address    
  274.     movl    sp@(4),d0            | d0 <= PMEG num
  275.     movsb    d0,a0@                | Write PMEG num to segment map
  276.     movl    sp@(8), a1            | a1 <= pteArray
  277. | Subtract off seg map offset and add page map offset into a0.
  278.     addl    #(VMMACH_PAGE_MAP_OFF - VMMACH_SEG_MAP_OFF), a0
  279.     movl    #VMMACH_NUM_PAGES_PER_SEG_INT, d1    | d1 <= Pmegs per seg.
  280. 1:
  281.     movsl    a0@, d0                | Read out the pte
  282.     movl    d0, a1@+            | a1 <= the pte
  283.     clrl    d0
  284.     movsl    d0, a0@                | Clear out the pte.
  285.     addl    #VMMACH_PAGE_SIZE_INT, a0    | Go to next address.
  286.     subql    #1, d1
  287.     bgt        1b            
  288.  
  289.     rts            
  290.  
  291.  
  292. |*
  293. |* ----------------------------------------------------------------------------
  294. |*
  295. |* VmMachTracePMEG --
  296. |*
  297. |*    Read out all page table entries in the given pmeg, generate trace
  298. |*    records for each with ref or mod bit set and then clear the ref
  299. |*    and mod bits.
  300. |*
  301. |*    void VmMachTracePMEG(pmeg)
  302. |*
  303. |* Results:
  304. |*      None.
  305. |*
  306. |* Side effects:
  307. |*    The reference and modified bits are cleared for all pages in
  308. |*    this PMEG.
  309. |*
  310. |* ----------------------------------------------------------------------------
  311. |*
  312.  
  313. #define    PTE_MASK (VMMACH_RESIDENT_BIT + VMMACH_REFERENCED_BIT + VMMACH_MODIFIED_BIT)
  314.  
  315.     .globl    _VmMachTracePMEG
  316. _VmMachTracePMEG:
  317.     movl    sp@(4), d0            | d0 <= PMEG num
  318.     moveml    #0x3020, sp@-            | Save d2, d3 and a2
  319.  
  320.     movl    _vmMachPMEGSegAddr, a2
  321.     addl    #VMMACH_SEG_MAP_OFF, a2        | a2 <= Segment map address    
  322.     movsb    d0,a2@                | Write PMEG num to segment map
  323. | Subtract off seg map offset and add page map offset into a2.
  324.     addl    #(VMMACH_PAGE_MAP_OFF - VMMACH_SEG_MAP_OFF), a2
  325.     movl    #VMMACH_NUM_PAGES_PER_SEG_INT, d3    | d3 <= Pmegs per seg.
  326. 1:
  327.     movsl    a2@, d2                | Read out the pte
  328.  
  329. |*
  330. |* Trace this page if it is resident and the reference and modify bits
  331. |* are set.
  332. |*
  333.  
  334.     movl    d2, d0
  335.     andl    #PTE_MASK, d0
  336.     beq        2f
  337.     cmpl    #VMMACH_RESIDENT_BIT, d0
  338.     beq        2f
  339.                         | Clear the ref and mod bits.
  340.     andl    #(~(VMMACH_REFERENCED_BIT + VMMACH_MODIFIED_BIT)), d2
  341.     movsl    d2, a2@
  342.  
  343. 2:
  344. |* 
  345. |* Go to the next page.
  346. |*
  347.     addl    #VMMACH_PAGE_SIZE_INT, a2    | Go to next address.
  348.     subql    #1, d3
  349.     bgt        1b            
  350.  
  351.     moveml    sp@+, #0x040c            | Restore a2, d3 and d2
  352.  
  353.     rts            
  354.  
  355. |*
  356. |* ----------------------------------------------------------------------------
  357. |*
  358. |* VmMachSetSegMap --
  359. |*
  360. |*         Set the segment map entry for the given virtual address to the given 
  361. |*    value.  It is assumed that the user context register is set to the 
  362. |*    context for which the segment map entry is to be set.
  363. |*
  364. |*    void VmMachSetSegMap(virtualAddress, value)
  365. |*        Address        virtualAddress;
  366. |*        unsigned char    value;
  367. |*
  368. |* Results:
  369. |*     None.
  370. |*
  371. |* Side effects:
  372. |*     Hardware segment map entry for the current user context is set.
  373. |*
  374. |* ----------------------------------------------------------------------------
  375. |*
  376.     .globl    _VmMachSetSegMap
  377. _VmMachSetSegMap:
  378.     movl    sp@(4),d0        | Get access address
  379.     andw    #VMMACH_SEG_MAP_MASK,d0    | Mask out low bits
  380.     addl    #VMMACH_SEG_MAP_OFF,d0    | Bump to segment map offset
  381.     movl    d0, a0
  382.     movl    sp@(8),d0        | Get segment map entry to write in a 
  383.                         | register.
  384.     movsb    d0,a0@            | Write segment map entry
  385.  
  386.     rts                        | return
  387.  
  388. |*
  389. |* ----------------------------------------------------------------------------
  390. |*
  391. |* VmMachSegMapCopy --
  392. |*
  393. |*         Copy the software segment map entries into the hardware segment entries.
  394. |*    All segment table entries between address startAddr and address
  395. |*    endAddr are copied.  It is assumed that the user context register is 
  396. |*    set to the context for which the segment map entries are to be set.
  397. |*    
  398. |*    void VmMachSegMapCopy(tablePtr, startAddr, endAddr)
  399. |*        char *tablePtr;
  400. |*        int startAddr;
  401. |*        int endAddr;
  402. |*
  403. |* Results:
  404. |*     None.
  405. |*
  406. |* Side effects:
  407. |*     Hardware segment map entries for the current user context are set.
  408. |*
  409. |* ----------------------------------------------------------------------------
  410. |*
  411.     .globl _VmMachSegMapCopy
  412. _VmMachSegMapCopy:
  413.     movl    sp@(4),a0        | Get segment table address
  414.     movl    sp@(8),d1        | Get start address in a register.
  415.     andw    #VMMACH_SEG_MAP_MASK,d1    | Mask out low bits
  416.     addl    #VMMACH_SEG_MAP_OFF,d1    | Bump to segment map offset
  417.     movl    d1, a1
  418.     movl    sp@(12),d1        | Get end address in a register.
  419.     addl    #VMMACH_SEG_MAP_OFF, d1    | Add in offset.
  420. 1:
  421.     movb    a0@,d0            | Get segment map entry to write.
  422.     movsb    d0,a1@            | Write segment map entry
  423.     addql    #1, a0            | Increment the address to copy from.
  424.     addl    #VMMACH_SEG_SIZE, a1    | Increment the address to copy to.
  425.     cmpl    a1, d1            | See if hit upper bound.  If not     
  426.     bgt        1b            | continue.
  427.  
  428.     rts
  429. /*
  430.  * Sun 2's require that the context offset be treated as a word and on Sun-3's
  431.  * it can't be.
  432.  */
  433.  
  434. #ifdef sun3
  435. #define    VMMACH_UC_OFF VMMACH_CONTEXT_OFF
  436. #define    VMMACH_KC_OFF VMMACH_CONTEXT_OFF
  437. #else
  438. #define    VMMACH_UC_OFF VMMACH_USER_CONTEXT_OFF:w
  439. #define    VMMACH_KC_OFF VMMACH_KERN_CONTEXT_OFF:w
  440. #endif
  441.  
  442. |*
  443. |* ----------------------------------------------------------------------------
  444. |*
  445. |* VmMachGetContextReg --
  446. |*
  447. |*         Return the value of the context register (on a Sun-2 the user context
  448. |*    register).
  449. |*
  450. |*    int VmMachGetContextReg()
  451. |*
  452. |* Results:
  453. |*     The value of context register.
  454. |*
  455. |* Side effects:
  456. |*     None.
  457. |*
  458. |* ----------------------------------------------------------------------------
  459. |*
  460.  
  461.     .globl    _VmMachGetContextReg
  462. _VmMachGetContextReg:
  463.                         | Move context reg into result 
  464.                             | register.
  465. #ifdef sun3
  466.     movsb    VMMACH_CONTEXT_OFF,d0         
  467. #else
  468.     movsb    VMMACH_USER_CONTEXT_OFF:w,d0
  469. #endif
  470.     andb    #VMMACH_CONTEXT_MASK,d0        | Clear high-order bits
  471.  
  472.     rts                        | Return
  473.  
  474. |*
  475. |* ----------------------------------------------------------------------------
  476. |*
  477. |* VmMachSetContextReg --
  478. |*
  479. |*         Set the user and kernel context registers to the given value.
  480. |*
  481. |*    void VmMachSetContext(value)
  482. |*        int value;        /* Value to set register to */
  483. |*
  484. |* Results:
  485. |*     None.
  486. |*
  487. |* Side effects:
  488. |*     None.
  489. |*
  490. |* ----------------------------------------------------------------------------
  491. |*
  492.     .globl    _VmMachSetContextReg
  493. _VmMachSetContextReg:
  494.  
  495.     movl    sp@(4),d0            | Get context value to set 
  496.                             | into a 
  497.                             | register
  498.  
  499.                         | Set context register(s).
  500. #ifdef sun3
  501.     movsb    d0, VMMACH_CONTEXT_OFF
  502. #else 
  503.     movsb    d0,VMMACH_USER_CONTEXT_OFF:w 
  504.     movsb    d0,VMMACH_KERN_CONTEXT_OFF:w
  505. #endif
  506.  
  507.     rts                        | Return
  508.  
  509. |*
  510. |* ----------------------------------------------------------------------------
  511. |*
  512. |* VmMachGetUserContext --
  513. |*
  514. |*         Return the value of the user context register.
  515. |*
  516. |*    int VmMachGetUserContext()
  517. |*
  518. |* Results:
  519. |*     The value of user context register.
  520. |*
  521. |* Side effects:
  522. |*     None.
  523. |*
  524. |* ----------------------------------------------------------------------------
  525. |*
  526.     .globl    _VmMachGetUserContext
  527. _VmMachGetUserContext:
  528.     movsb    VMMACH_UC_OFF,d0         | Get context reg value
  529.     andb    #VMMACH_CONTEXT_MASK,d0        | Clear high-order bits
  530.     rts                        | Return
  531.  
  532. |*
  533. |* ----------------------------------------------------------------------------
  534. |*
  535. |* VmMachGetKernelContext --
  536. |*
  537. |*         Return the value of the kernel context register.
  538. |*
  539. |*    int VmMachGetKernelContext()
  540. |*
  541. |* Results:
  542. |*     The value of kernel context register.
  543. |*
  544. |* Side effects:
  545. |*     None.
  546. |*
  547. |* ----------------------------------------------------------------------------
  548. |*
  549.     .globl    _VmMachGetKernelContext
  550. _VmMachGetKernelContext:
  551.     movsb    VMMACH_KC_OFF,d0         | Get context reg value.
  552.     andb    #VMMACH_CONTEXT_MASK,d0        | Clear high-order bits
  553.     rts
  554.  
  555. |*
  556. |* ----------------------------------------------------------------------------
  557. |*
  558. |* VmMachSetUserContext --
  559. |*
  560. |*         Set the user context register to the given value.
  561. |*
  562. |*    void VmMachSetUserContext(value)
  563. |*        int value;        /* Value to set register to */
  564. |*
  565. |* Results:
  566. |*     None.
  567. |*
  568. |* Side effects:
  569. |*     None.
  570. |*
  571. |* ----------------------------------------------------------------------------
  572. |*
  573.  
  574.     .globl    _VmMachSetUserContext
  575. _VmMachSetUserContext:
  576.     movl    sp@(4),d0            | Get context value to set.
  577.     movsb    d0,VMMACH_UC_OFF         | Set context register.
  578.     rts                        | Return
  579.  
  580. |*
  581. |* ----------------------------------------------------------------------------
  582. |*
  583. |* VmMachSetKernelContext --
  584. |*
  585. |*         Set the kernel context register to the given value.
  586. |*
  587. |*    void VmMachSetKernelContext(value)
  588. |*        int value;        /* Value to set register to */
  589. |*
  590. |* Results:
  591. |*     None.
  592. |*
  593. |* Side effects:
  594. |*     The supervisor context is set.
  595. |*
  596. |* ----------------------------------------------------------------------------
  597. |*
  598.  
  599.     .globl    _VmMachSetKernelContext
  600. _VmMachSetKernelContext:
  601.     movl    sp@(4),d0            | Get context value to set
  602.     movsb    d0,VMMACH_KC_OFF         | Set context register
  603.     rts                     | Return
  604.  
  605.  
  606. |*
  607. |* ----------------------------------------------------------------------
  608. |*
  609. |* Vm_Copy{In,Out}
  610. |*
  611. |*    Copy numBytes from *sourcePtr in to *destPtr.
  612. |*    This routine is optimized to do transfers when sourcePtr and 
  613. |*    destPtr are both 4-byte aligned.
  614. |*
  615. |*    void
  616. |*    Vm_Copy{In,Out}(numBytes, sourcePtr, destPtr)
  617. |*        register int numBytes;      /* The number of bytes to copy */
  618. |*        Address sourcePtr;          /* Where to copy from. */
  619. |*        Address destPtr;            /* Where to copy to. */
  620. |*
  621. |*    NOTE: The trap handler assumes that this routine does not push anything
  622. |*          onto the stack.  It uses this fact to allow it to return to the
  623. |*          caller of this routine upon an address fault.  If you must push
  624. |*          something onto the stack then you had better go and modify 
  625. |*          "CallTrapHandler" in asmDefs.h appropriately.
  626. |*
  627. |* Results:
  628. |*    Returns SUCCESS if the copy went OK (which is almost always).  If
  629. |*    a bus error (other than a page fault) occurred while reading or
  630. |*    writing user memory, then SYS_ARG_NO_ACCESS is returned (this return
  631. |*    occurs from the trap handler, rather than from this procedure).
  632. |*
  633. |* Side effects:
  634. |*    The area that destPtr points to is modified.
  635. |*
  636. |* ----------------------------------------------------------------------
  637. |*
  638.     .globl _VmMachDoCopy
  639.     .globl _Vm_CopyIn
  640. _VmMachDoCopy:
  641. _Vm_CopyIn:
  642.     movl    sp@(4),d1            | Get number of bytes into a
  643.                         |     register.
  644.     movl        sp@(8),a0            | Get source and dest addresses
  645.     movl        sp@(12),a1            |     into a register.
  646.  
  647. |*
  648. |* If the source or dest are not 2 byte aligned then everything must be
  649. |* done as byte copies.
  650. |*
  651.  
  652. gotArgs:
  653.     movl        a0,d0
  654.     orl        sp@(12),d0
  655.     andl    #1,d0
  656.     jne        3f
  657.  
  658. |*
  659. |* Do as many 64-byte copies as possible.
  660. |*
  661.  
  662. 1:
  663.     cmpl        #64,d1
  664.     jlt         2f
  665.     movl       a0@+, a1@+
  666.     movl       a0@+, a1@+
  667.     movl       a0@+, a1@+
  668.     movl       a0@+, a1@+
  669.     movl       a0@+, a1@+
  670.     movl       a0@+, a1@+
  671.     movl       a0@+, a1@+
  672.     movl       a0@+, a1@+
  673.     movl       a0@+, a1@+
  674.     movl       a0@+, a1@+
  675.     movl       a0@+, a1@+
  676.     movl       a0@+, a1@+
  677.     movl       a0@+, a1@+
  678.     movl       a0@+, a1@+
  679.     movl       a0@+, a1@+
  680.     movl       a0@+, a1@+
  681.     subl       #64,d1
  682.     jra         1b
  683.  
  684. |*
  685. |* Copy up to 64 bytes of remainder, in 4-byte chunks.  Do this quickly
  686. |* by dispatching into the middle of a sequence of move instructions.
  687. |*
  688.  
  689. 2:
  690.     movl    d1,d0
  691.     andl    #3,d1
  692.     subl    d1,d0
  693.     asrl    #1,d0
  694.     negl    d0
  695.     jmp        pc@(34, d0:w)    
  696.     movl       a0@+, a1@+
  697.     movl       a0@+, a1@+
  698.     movl       a0@+, a1@+
  699.     movl       a0@+, a1@+
  700.     movl       a0@+, a1@+
  701.     movl       a0@+, a1@+
  702.     movl       a0@+, a1@+
  703.     movl       a0@+, a1@+
  704.     movl       a0@+, a1@+
  705.     movl       a0@+, a1@+
  706.     movl       a0@+, a1@+
  707.     movl       a0@+, a1@+
  708.     movl       a0@+, a1@+
  709.     movl       a0@+, a1@+
  710.     movl       a0@+, a1@+
  711.     movl       a0@+, a1@+
  712.  
  713. |*
  714. |* Do one byte copies until done.
  715. |*
  716.  
  717. 3:
  718.     tstl        d1
  719.     jle         4f
  720.     movb       a0@+,a1@+
  721.     subql       #1,d1
  722.     jra         3b
  723.  
  724. |* 
  725. |* Return.
  726. |*
  727.  
  728. 4: 
  729.     clrl    d0
  730.     rts
  731.  
  732. |* Vm_CopyOut is just like Vm_CopyIn except that it checks to make sure
  733. |* that the destination is in the user area (otherwise this would be a
  734. |* trap door to write to kernel space).
  735.  
  736.     .globl _Vm_CopyOut, _mach_FirstUserAddr, _mach_LastUserAddr
  737. _Vm_CopyOut:
  738.     movl    sp@(4),d1            | Get number of bytes into a
  739.                         |     register.
  740.     movl        sp@(8),a0            | Get source and dest addresses
  741.     movl        sp@(12),a1            |     into a register.
  742.     cmpl    _mach_FirstUserAddr,a1
  743.     jcs        5f
  744.     movl    a1,d0
  745.     subql    #1,d0
  746.     addl    d1,d0
  747.     jcs        5f
  748.     cmpl    _mach_LastUserAddr,d0
  749.     jls        gotArgs
  750.  
  751. |* User address out of range.  Check for a zero byte count before
  752. |* returning an error, though;  there appear to be kernel routines
  753. |* that call Vm_CopyOut with a zero count but bogus other arguments.
  754.  
  755. 5:
  756.     tstl    d1
  757.     jne        6f
  758.     clrl    d0
  759.     rts
  760. 6:
  761.     movl    #0x20000,d0
  762.     rts
  763.  
  764. |*
  765. |* ----------------------------------------------------------------------
  766. |*
  767. |* Vm_StringNCopy
  768. |*
  769. |*    Copy the NULL terminated string from *sourcePtr to *destPtr up
  770. |*    numBytes worth of bytes.
  771. |*
  772. |*    ReturnStatus
  773. |*    Vm_StringNCopy(numBytes, sourcePtr, destPtr, bytesCopiedPtr)
  774. |*        register int numBytes;      /* The number of bytes to copy */
  775. |*        Address sourcePtr;          /* Where to copy from. */
  776. |*        Address destPtr;            /* Where to copy to. */
  777. |*        int    *bytesCopiedPtr;    /* Number of bytes copied. */
  778. |*
  779. |*    NOTE: The trap handler assumes that this routine does not push anything
  780. |*          onto the stack.  It uses this fact to allow it to return to the
  781. |*          caller of this routine upon an address fault.  If you must push
  782. |*          something onto the stack then you had better go and modify 
  783. |*          "CallTrapHandler" in asmDefs.h appropriately.
  784. |*
  785. |* Results:
  786. |*    Normally returns SUCCESS.  If a non-recoverable bus error occurs,
  787. |*    then the trap handler fakes up a SYS_ARG_NO_ACCESS return from
  788. |*    this procedure.
  789. |*
  790. |* Side effects:
  791. |*    The area that destPtr points to is modified and *bytesCopiedPtr 
  792. |*    contains the number of bytes copied.
  793. |*
  794. |* ----------------------------------------------------------------------
  795. |*
  796.     .globl  _Vm_StringNCopy
  797. _Vm_StringNCopy:
  798.     movl        sp@(4),d1            | Get number of bytes into a
  799.                         |     register.
  800.     movl        sp@(8),a0            | Get source and dest addresses
  801.     movl        sp@(12),a1            |     into a register.
  802.  
  803. 1: 
  804.     movb    a0@, a1@+            | Copy the character.
  805.     cmpb    #0, a0@+            | See if hit null in string.
  806.     beq        2f
  807.     subl    #1, d1                | Decrement the byte counter.
  808.     bne        1b                | Copy more chars if haven't
  809.                         |     reached the limit.
  810. 2: 
  811.     movl    sp@(4), d0            | Compute the number of bytes
  812.     subl    d1, d0                |     copied and store the
  813.     movl    sp@(16), a0            |     result.
  814.     movl    d0, a0@
  815.     clrl    d0                | Return SUCCESS.
  816.     rts
  817.  
  818.  
  819. |*
  820. |* ----------------------------------------------------------------------
  821. |*
  822. |* Vm_TouchPages --
  823. |*
  824. |*    Touch the range of pages.
  825. |*
  826. |*    void
  827. |*    Vm_TouchPages(firstPage, numPages)
  828. |*        int    firstPage;    /* First page to touch. */
  829. |*        int    numPages;    /* Number of pages to touch. */
  830. |*
  831. |*    NOTE: The trap handler assumes that this routine does not push anything
  832. |*          onto the stack.  It uses this fact to allow it to return to the
  833. |*          caller of this routine upon an address fault.  If you must push
  834. |*          something onto the stack then you had better go and modify 
  835. |*          "CallTrapHandler" in asmDefs.h appropriately.
  836. |*
  837. |* Results:
  838. |*    Returns SUCCESS if were able to touch the page (which is almost
  839. |*    always).  If a bus error (other than a page fault) occurred while 
  840. |*    reading user memory, then SYS_ARG_NO_ACCESS is returned (this return
  841. |*    occurs from the trap handler, rather than from this procedure).
  842. |*
  843. |* Side effects:
  844. |*    None.
  845. |*
  846. |* ----------------------------------------------------------------------
  847. |*
  848.     .globl _Vm_TouchPages
  849. _Vm_TouchPages:
  850.     movl    sp@(4),d0    | d0 <= firstPage
  851.     movl    #VMMACH_PAGE_SHIFT, d1
  852.     asll    d1, d0        | d0 <= d0 << VMMACH_PAGE_SIZE
  853.     movl    d0, a0        | a0 <= Starting address    
  854.     movl    sp@(8), d0    | d0 <= numPages
  855. 1:
  856.     tstl    d0        | Quit when d0 == 0
  857.     jeq        2f
  858.     movl    a0@, d1        | Touch the page at the address in a0
  859.     subql    #1, d0        | Go back around to touch the next page.
  860.     addl    #VMMACH_PAGE_SIZE, a0
  861.     jra        1b
  862.  
  863. 2:
  864.     rts
  865.  
  866. |*
  867. |* The address marker below is there so that the trap handler knows the
  868. |* end of code that may take a page fault while copying into/out of
  869. |* user space.
  870.  
  871.     .globl _VmMachCopyEnd
  872. _VmMachCopyEnd:
  873.